using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;

namespace RStein.Posterous.API
{
    internal class PosterousAuthor : IAuthor, IEquatable<PosterousAuthor>
    {
        #region Constants
        public static readonly string UNKNOWN_AUTHOR = "<None>";
        public static readonly string UNKNOWN_EMAIL= "none@none.none";

        private static PosterousAuthor _unknownAuthor = new PosterousAuthor
                                                            {
                                                                Name = UNKNOWN_AUTHOR,
                                                                Email = UNKNOWN_EMAIL
                                                            };
        #endregion Constants
        #region private variables
        private Stream m_authPicture;
        #endregion private variables
        
        #region Constructors

        public PosterousAuthor()
        {            
            IsAuthorPictureLoaded = false;
            Name = UNKNOWN_AUTHOR;
            Email = UNKNOWN_EMAIL;
        }

        #endregion Constructors

        #region Implementation of IExtensionInterface

        public T GetInterface<T>() where T : class
        {
            return this as T;
        }

        #endregion

        #region methods

        public bool Equals(PosterousAuthor other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }
            if (ReferenceEquals(this, other))
            {
                return true;
            }
            return Equals(other.Name, Name) && Equals(other.Email, Email);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != typeof (PosterousAuthor))
            {
                return false;
            }
            return Equals((PosterousAuthor) obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (Name.GetHashCode()*397) ^ Email.GetHashCode();
            }
        }

        public static bool operator ==(PosterousAuthor left, PosterousAuthor right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(PosterousAuthor left, PosterousAuthor right)
        {
            return !Equals(left, right);
        }

        public static PosterousAuthor GetUnknownAuthor()
        {
            return _unknownAuthor;
        }

        #endregion methods
        #region Implementation of IAuthor

        public string Name
        {
            get; 
            set;
        }

        public string Email
        {
            get;
            set;            
        }

        public string AuthorPictureUrl
        {
            get; 
            set;
        }        

        public Stream AuthorPicture
        {
            get
            {
                if ( String.IsNullOrEmpty( AuthorPictureUrl))
                {
                    throw new PosterousException(GlobalConstants.MISSING_AUTHOR_URL);
                }

                if (!IsAuthorPictureLoaded)
                {
                    LoadAuthorPicture();
                }
                
                return m_authPicture;
            }
            set
            {
                m_authPicture = value;
            }
        }        

        public bool IsAuthorPictureLoaded
        {
            get; 
            set;
        }


        public void LoadAuthorPicture()
        {            
            if (String.IsNullOrEmpty(AuthorPictureUrl))
            {
                m_authPicture = new MemoryStream();
            }
            else
            {
                var downloader = SimpleWebFactory.Instance.Create<ISimpleDownloader>();
                m_authPicture = downloader.DownloadFile(AuthorPictureUrl);
                IsAuthorPictureLoaded = true;
            }
            
            var evArgs = new EventArgsValue<Stream>(m_authPicture, null);
            OnAuthorPictureLoaded(evArgs);
            
            
        }


        public void LoadAuthorPictureAsync()
        {
            Action<Exception> exchandler = e =>
            {
                var ex = new PosterousException(GlobalConstants.ASYNC_EXCEPTION_TEXT, e);
                OnAuthorPictureLoaded(new EventArgsValue<Stream>(null, ex));
            };

            AsyncHelper.RunDelegateAsync((Action) LoadAuthorPicture, exchandler, null);            
                        
        }

        public event EventHandler<EventArgsValue<Stream>> AuthorPictureLoaded;

        public void OnAuthorPictureLoaded(EventArgsValue<Stream> e)
        {
            EventHandler<EventArgsValue<Stream>> handler = AuthorPictureLoaded;
            if (handler != null)
            {
                Thread.CurrentThread.GetCurrentSynchronizationContext().Post(o => handler(this, e), null);
            }
        }

        #endregion
    }
}
